package com.cjb.cloudsystem.service.impl;

import com.cjb.cloudsecurity.JWT.TokenStoreCache;
import com.cjb.cloudsecurity.userMsg.entity.UserDetail;
import com.cjb.cloudsystem.entity.SysLogLogin;
import com.cjb.cloudsystem.entity.SysParams;
import com.cjb.cloudsystem.entity.SysUser;
import com.cjb.cloudsystem.entity.SysUserToken;
import com.cjb.cloudsystem.enums.LoginOperationEnum;
import com.cjb.cloudsystem.service.*;
import com.cjb.cloudsystem.vo.SysAccountLoginVO;
import com.cjb.cloudsystem.vo.SysParamsVO;
import com.cjb.common.common.cache.RedisCache;
import com.cjb.common.common.constant.Constant;
import com.cjb.common.exception.ServerException;
import com.cjb.common.util.*;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * All rights Reserved, Designed By  chenjinbin
 *
 * @author chenjinbin
 * @Project: fjbd_cjb_bs
 * @Package com.cjb.cloudsystem.service.impl
 * @title SysAuthServiceImpl
 * @Description
 * @email
 * @date 2023-08-29 16:47
 * @since JDK 1.8
 */
@Service
public class SysAuthServiceImpl implements SysAuthService {
    /**
     * 日志
     */
    private final static Logger log = LoggerFactory.getLogger(SysAuthServiceImpl.class);
    /**
     * 参数管理 KEY
     */
    private final String SYSTEM_PARAMS_KEY = "system:params";
    /**
     * 作用域
     */
    private final String FIELD="USER_DEFAULT_IMG";
    /*
     * 注入事物类
     */
    @Autowired
    private SysUserService sysUserService;
    /**
     * 注入参数管理服务类
     */
    @Autowired
    private SysParamsService sysParamsService;
    /**
     * 注入缓存事务类
     */
    @Autowired
    private RedisCache redisCache;
    /**
     * 操作日志类
     */
    @Autowired
    private SysLogLoginService sysLogLoginService;
    /**
     * 责任链
     */
    @Autowired
    private AuthenticationManager authenticationManager;
    /**
     * token 服务类
     */
    @Autowired
    private SysUserTokenService sysUserTokenService;

    /**
     * token缓冲区
     */
    @Autowired
    private TokenStoreCache tokenStoreCache;

    /**
     * 账号密码登录
     *
     * @param login 登录信息
     */
    @Override
    public SysUserToken loginByAccount(SysAccountLoginVO login) {
        //验证码校验
        boolean flag = sysParamsService.validateCaptcha(login.getKey(), login.getCaptcha());
        log.info("验证码结果为{}", flag);
        log.info("打印验证码名称 {}",login.getCaptcha());
        log.info("打印验证码key {}",login.getKey());
        if (!flag) {
            //日志记录失败信息
            SysLogLogin sysLogLogin = new SysLogLogin();
            sysLogLogin.setUsername(login.getUsername());
            sysLogLogin.setStatus(Constant.FAIL);
            sysLogLogin.setOperation(LoginOperationEnum.CAPTCHA_FAIL.getValue());
            log.info("记录异常信息 {}",JsonUtils.toJsonString(sysLogLogin));
            sysLogLoginService.save(sysLogLogin);

            //异常抛出
            throw new ServerException("验证码错误");
        }

        //责任链身份认证
        Authentication authentication;
        //责任链信息认证
        try {
            log.info("进入身份认证..");
            authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(login.getUsername(), login.getPassword()));
        } catch (BadCredentialsException e) {
            log.error("失败信息{}", e);
            throw new ServerException("身份认证失败" + e);
        }

        //用户信息
        UserDetail user = (UserDetail) authentication.getPrincipal();

        //生成accessToken todo 可能会再往token里面加东西
        SysUserToken sysUserToken = new SysUserToken();
        sysUserToken.setUserId(user.getId());

        //生成token
        SysUserToken token = sysUserTokenService.createToken(sysUserToken);
        log.info("打印生成的token信息 {}", JsonUtils.toJsonString(token));
        // 保存用户信息到缓存
        tokenStoreCache.saveUser(sysUserToken.getAccessToken(), user);

        //保存在日志
        SysLogLogin sysLogLogin = new SysLogLogin();

        String userAgent = HttpContextUtils.getHttpServletRequest().getHeader(HttpHeaders.USER_AGENT);
        String ip = IpUtils.getIpAddr(HttpContextUtils.getHttpServletRequest());
        log.info("打印记录的IP地址 {}",ip);
        String address = AddressUtils.getAddressByIP(ip);

        sysLogLogin.setUserAgent(userAgent);
        sysLogLogin.setIp(ip);
        sysLogLogin.setAddress(address);

        sysLogLogin.setStatus(Constant.SUCCESS);
        sysLogLogin.setOperation(LoginOperationEnum.LOGIN_SUCCESS.getValue());
        sysLogLogin.setUsername(IpUtils.getHostName());
        sysLogLoginService.save(sysLogLogin);
        return token;
    }
    /**
     * 账号注册
     *
     * @Author chenjinbin
     * @Value
     * @Title
     */
    @Override
    public SysUserToken registerByAccount(SysAccountLoginVO login) {
        //验证码校验
        boolean flag = sysParamsService.validateCaptcha(login.getKey(), login.getCaptcha());
        log.info("验证码结果为{}", flag);
        log.info("打印验证码名称 {}",login.getCaptcha());
        log.info("打印验证码key {}",login.getKey());
        if (!flag) {
            //日志记录失败信息
            SysLogLogin sysLogLogin = new SysLogLogin();
            sysLogLogin.setUsername(login.getUsername());
            sysLogLogin.setStatus(Constant.FAIL);
            sysLogLogin.setOperation(LoginOperationEnum.CAPTCHA_FAIL.getValue());
            log.info("记录异常信息 {}",JsonUtils.toJsonString(sysLogLogin));
            sysLogLoginService.save(sysLogLogin);

            //异常抛出
            throw new ServerException("验证码错误");
        }

        //注册校验
        //进行注册
        log.info("打印注册信息 {}",login);
        if (Common.isNotEmptyVales(login,login.getUsername(),login.getPassword())){
            //数据库查询重复
            Long countUserByNameAndPassword = sysUserService.countUserByNameAndPassword(login.getUsername(), login.getPassword());
            if (countUserByNameAndPassword>0){
                new ServerException("注册的用户名密码重复");
            }
            SysUser sysUser = new SysUser();
            sysUser.setUsername(login.getUsername());

            String imgSrc = (String)redisCache.hGet(SYSTEM_PARAMS_KEY, FIELD);
            //默认的图像  没有去参数管理中寻找
            if (Common.isEmpty(imgSrc) || imgSrc.equals("")){
                SysParamsVO sysParamsVO = new SysParamsVO();
                sysParamsVO.setParamKey("USER_DEFAULT_IMG");
                List<SysParams> params = sysParamsService.queryBySysParams(sysParamsVO);
                if (Common.isNotEmpty(params)){
                    imgSrc = params.get(0).getParamValue();
                }
            }
            sysUser.setAvatar(imgSrc);
            //默认非超级管理员
            if (Common.isNotEmpty(sysUser)&&Common.isEmpty(sysUser.getSuperAdmin())){
                sysUser.setSuperAdmin(0);
            }
            sysUserService.save(sysUser);
        }

        //保存在日志
        SysLogLogin sysLogLogin = new SysLogLogin();

        String userAgent = HttpContextUtils.getHttpServletRequest().getHeader(HttpHeaders.USER_AGENT);
        String ip = IpUtils.getHostIp();
        String address = AddressUtils.getAddressByIP(ip);

        sysLogLogin.setUserAgent(userAgent);
        sysLogLogin.setIp(ip);
        sysLogLogin.setAddress(address);

        sysLogLogin.setStatus(Constant.SUCCESS);
        sysLogLogin.setOperation(LoginOperationEnum.REGISTER_LOGOUT_SUCCESS.getValue());
        sysLogLogin.setUsername(IpUtils.getHostName());
        sysLogLoginService.save(sysLogLogin);
        return null;
    }
}
